package io.gitee.zhangbinhub.admin.oauth.controller.api

import cn.dev33.satoken.annotation.SaCheckPermission
import cn.dev33.satoken.stp.StpUtil
import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.boot.log.LogAdapter
import io.gitee.zhangbinhub.acp.cloud.resource.server.tools.TokenTools
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.common.api.OauthApi
import io.gitee.zhangbinhub.admin.common.constant.ModuleFuncCode
import io.gitee.zhangbinhub.admin.common.constant.RoleCode
import io.gitee.zhangbinhub.admin.common.vo.BooleanInfoVo
import io.gitee.zhangbinhub.admin.common.vo.InfoVo
import io.gitee.zhangbinhub.admin.oauth.entity.Menu
import io.gitee.zhangbinhub.admin.oauth.entity.ModuleFunc
import io.gitee.zhangbinhub.admin.oauth.po.MenuPo
import io.gitee.zhangbinhub.admin.oauth.po.ModuleFuncPo
import io.gitee.zhangbinhub.admin.oauth.service.MenuService
import io.gitee.zhangbinhub.admin.oauth.service.ModuleFuncService
import io.gitee.zhangbinhub.admin.oauth.vo.MenuVo
import io.gitee.zhangbinhub.admin.oauth.vo.ModuleFuncVo
import io.gitee.zhangbinhub.admin.resource.server.base.BaseResourceServerController
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import org.noear.solon.annotation.*
import org.noear.solon.core.handle.MethodType
import org.noear.solon.core.util.MimeType
import org.noear.solon.validation.annotation.*

@Valid
@Controller
@Api("权限信息")
open class AuthController(
    private val logAdapter: LogAdapter,
    private val menuService: MenuService,
    private val moduleFuncService: ModuleFuncService
) : BaseResourceServerController(logAdapter) {

    private val moduleFuncCodeList: MutableList<String> = mutableListOf()

    @ApiOperation("获取模块功能编码列表")
    @SaCheckPermission(ModuleFuncCode.authConfig, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.moduleFuncCodes,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    fun findModuleFuncCode(): List<String> = moduleFuncCodeList

    @Init
    fun init() {
        try {
            for (field in ModuleFuncCode::class.java.declaredFields) {
                val value = field.get(ModuleFuncCode::class.java)
                if (value is String) {
                    moduleFuncCodeList.add(value)
                }
            }
            moduleFuncCodeList.sort()
        } catch (e: Exception) {
            logAdapter.error(e.message, e)
        }

    }

    @ApiOperation("判断当前用户是否具有指定的权限")
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.authentication + "/{authentication}",
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun currUserHasAuthentication(@Path(name = "authentication") authentication: String): BooleanInfoVo =
        BooleanInfoVo(result = hasAuthentication(mutableListOf(authentication)))

    @ApiOperation("获取当前用户所属菜单", notes = "根据当前登录的用户信息，查询有权访问的菜单列表")
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.currMenu,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun currMenuList(): List<Menu> = menuService.getMenuList(
        TokenTools.getAccessTokenModel()?.clientId ?: "", StpUtil.getLoginIdAsString()
    )

    @ApiOperation("获取当前用户所有功能权限信息", notes = "根据当前登录的用户信息，查询具备的功能权限")
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.currModuleFunc,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun currModuleFuncList(): List<ModuleFunc> = moduleFuncService.getModuleFuncList(
        TokenTools.getAccessTokenModel()?.clientId ?: "", StpUtil.getLoginIdAsString()
    )

    @ApiOperation("获取指定应用下的菜单列表", notes = "查询指定应用的菜单列表，供选择配置")
    @SaCheckPermission(ModuleFuncCode.authQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.menuList + "/{appId}", produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun menuList(@Path(name = "appId") appId: String): List<Menu> = menuService.getMenuListByAppId(appId)

    @ApiOperation("获取指定应用下的模块功能列表", notes = "查询指定应用的模块功能列表，供选择配置")
    @SaCheckPermission(ModuleFuncCode.authQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.moduleFuncList + "/{appId}", produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun moduleFuncList(@Path(name = "appId") appId: String): List<ModuleFunc> =
        moduleFuncService.getModuleFuncListByAppId(appId)

    @ApiOperation("获取菜单列表", notes = "查询所有菜单列表")
    @SaCheckPermission(ModuleFuncCode.authQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.menuConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    fun allMenuList(): List<Menu> = menuService.getAllMenuList()

    @ApiOperation("获取模块功能列表", notes = "查询所有模块功能列表")
    @SaCheckPermission(ModuleFuncCode.authQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.moduleFuncConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    fun allModuleFuncList(): List<ModuleFunc> = moduleFuncService.getAllModuleFuncList()

    @ApiOperation("新建菜单信息", notes = "名称、应用ID、图标、链接、上级、序号、模式、状态、关联角色")
    @SaCheckPermission(ModuleFuncCode.authAdd, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.PUT],
        value = OauthApi.basePath + OauthApi.menuConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    fun addMenu(@Body @Validated menuPo: MenuPo): Menu = menuService.doCreate(StpUtil.getLoginIdAsString(), menuPo)

    @ApiOperation("新建模块功能信息", notes = "名称、应用ID、编码、上级、关联角色")
    @SaCheckPermission(ModuleFuncCode.authAdd, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.PUT],
        value = OauthApi.basePath + OauthApi.moduleFuncConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    fun addModuleFunc(@Body @Validated moduleFuncPo: ModuleFuncPo): ModuleFunc =
        moduleFuncService.doCreate(StpUtil.getLoginIdAsString(), moduleFuncPo)

    @ApiOperation("删除指定的菜单信息")
    @SaCheckPermission(ModuleFuncCode.authDelete, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.DELETE],
        value = OauthApi.basePath + OauthApi.menuConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun deleteMenu(
        @ApiParam("id列表", required = true)
        @NotEmpty(message = "id不能为空")
        @NotNull(message = "id不能为空")
        @Body idList: MutableList<String>
    ): InfoVo = menuService.doDelete(idList).let { InfoVo(message = "删除成功") }

    @ApiOperation("删除指定的模块功能信息")
    @SaCheckPermission(ModuleFuncCode.authDelete, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.DELETE],
        value = OauthApi.basePath + OauthApi.moduleFuncConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun deleteModuleFunc(
        @ApiParam("id列表", required = true)
        @NotEmpty(message = "id不能为空")
        @NotNull(message = "id不能为空")
        @Body idList: MutableList<String>
    ): InfoVo = moduleFuncService.doDelete(idList).let { InfoVo(message = "删除成功") }

    @ApiOperation("更新菜单信息", notes = "名称、应用ID、图标、链接、上级、序号、模式、状态、关联角色")
    @SaCheckPermission(ModuleFuncCode.authUpdate, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.PATCH],
        value = OauthApi.basePath + OauthApi.menuConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun updateMenu(@Body @Validated menuPo: MenuPo): Menu {
        if (CommonTools.isNullStr(menuPo.id)) {
            throw WebException("配置ID不能为空")
        }
        return menuService.doUpdate(StpUtil.getLoginIdAsString(), menuPo)
    }

    @ApiOperation("更新模块功能信息", notes = "名称、应用ID、编码、上级、关联角色")
    @SaCheckPermission(ModuleFuncCode.authUpdate, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.PATCH],
        value = OauthApi.basePath + OauthApi.moduleFuncConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun updateModuleFunc(@Body @Validated moduleFuncPo: ModuleFuncPo): ModuleFunc {
        if (CommonTools.isNullStr(moduleFuncPo.id)) {
            throw WebException("配置ID不能为空")
        }
        return moduleFuncService.doUpdate(StpUtil.getLoginIdAsString(), moduleFuncPo)
    }

    @ApiOperation("获取菜单详细信息")
    @SaCheckPermission(ModuleFuncCode.authQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.menuConfig + "/{menuId}",
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun menuInfo(
        @ApiParam("菜单id", required = true)
        @NotBlank(message = "菜单id不能为空")
        @Path(name = "menuId") menuId: String
    ): MenuVo = menuService.getMenuInfo(menuId)

    @ApiOperation("获取模块功能详细信息")
    @SaCheckPermission(ModuleFuncCode.authQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = OauthApi.basePath + OauthApi.moduleFuncConfig + "/{moduleFuncId}",
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun moduleFuncInfo(
        @ApiParam("模块功能id", required = true)
        @NotBlank(message = "模块功能id不能为空")
        @Path(name = "moduleFuncId") moduleFuncId: String
    ): ModuleFuncVo = moduleFuncService.getModuleFuncInfo(moduleFuncId)

}
